package com.mt.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.Digester;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mt.dto.ModifyPasswordRequest;
import com.mt.utils.IdUtils;
import com.mt.enums.RoleType;
import com.mt.constants.SYS;
import com.mt.enums.Sex;
import com.mt.enums.Status;
import com.mt.exception.GlobalException;
import com.mt.mapper.AclMapper;
import com.mt.mapper.UserMapper;
import com.mt.pojo.Acl;

import com.mt.pojo.User;
import com.mt.service.UserService;
import com.mt.util.MessageUtil;
import com.mt.utils.JWTUtil;
import com.mt.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Wang
 * @since 2020-11-12
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    UserMapper userMapper;
    @Resource
    AclMapper aclMapper;
    @Autowired
    RedisUtils redisUtil;
    @Autowired
    MessageUtil messageUtil;


    /**
     *  url和acl_code  只同时传一个值
    */

    @Override
    public String AuthUser(String token, String type, String url, String aclCode) {
        if (url != null && StrUtil.isNotBlank(aclCode)){
            throw new GlobalException(Status.PARAM_ERROR);
        }
        //解析token,提取user
        String userId;
        try {
            userId=  JWT.decode(token).getClaim("userId").asString();
            Object o = redisUtil.get("user::" + userId);
            if (! token.equals(o.toString())){
                throw new GlobalException(Status.LOGIN_ERROR,"token校验失败");
            }
        }catch (RuntimeException e){
            throw new GlobalException(Status.LOGIN_ERROR,"token校验失败");
        }
        if ("".equals(userId)){
            throw new GlobalException(Status.LOGIN_ERROR,"token校验失败");
        }
        List<Integer> aclList = userMapper.listAclByUser(userId);
        System.out.println(aclList.toString());
        Acl acl = null;
        if (url != null) {
            //处理url
            acl = aclMapper.selectOne(Wrappers.<Acl>lambdaQuery().eq(Acl::getRequestType, type).eq(Acl::getUrl,url));
        } else if (StrUtil.isNotBlank(aclCode)) {
            acl = aclMapper.selectOne(Wrappers.<Acl>lambdaQuery().eq(Acl::getAclCode, aclCode));
        }
//        aclList.contains(acl.getId()) ? userId : null;
        return userId;

    }


    @Override
    public User getUserInfo(String userId){
        User user = userMapper.getUserBriefInfo(userId);
        return user;
    }

    @Override
    public User getUserDetailInfo(String userId){
        User user = userMapper.selectById(userId);
        return user;
    }


    //todo 逻辑完善
    @Override
    public User  modifyUser(User user){
        if (StrUtil.isNotBlank(user.getPassword())){
            Digester digester = DigestUtil.digester("sm3");
            String digesterPw = digester.digestHex(user.getPassword());
            user.setPassword(digesterPw);
        }
        boolean b = userMapper.modifyUser(user);
        if (b){
            return user;
        }else{
            throw new GlobalException(Status.ERROR);
        }
    }
    @Override
    public User  modifyUserPassword(ModifyPasswordRequest request){
        if (StrUtil.isBlank(request.getOldPassword()) || StrUtil.isBlank(request.getNewPassword()) ){
            throw new GlobalException(Status.PARAM_ERROR);
        }
        //加密
        Digester digester = DigestUtil.digester("sm3");
        String digesterOldPw = digester.digestHex(request.getOldPassword());
        String digesterNewPw = digester.digestHex(request.getNewPassword());
        User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getId, request.getUserId()).eq(User::getPassword, digesterOldPw));
       if (user == null ){
           throw new GlobalException(Status.PASSWORD_ERROR);
       }
        user.setPassword(digesterNewPw);
        boolean b = userMapper.modifyUser(user);
        if (b){
            return user;
        }else{
            throw new GlobalException(Status.ERROR);
        }
    }

    @Override
    public  IPage<User> listUserInfo(Integer curPage, Integer pageSize, String key) {
        IPage<User> page = new Page<>(curPage,pageSize);
        if (StrUtil.isNotBlank(key)) {
            key = "%"+key+"%";
        }else {
            key =null;
        }
        List<User> users = userMapper.listUser(page, key);
        page.setRecords(users);
        return  page;
    }

    @Override
    public String login(User user) {
        String token = null;
        List<User> userList = userMapper.selectList(Wrappers.<User>lambdaQuery()
                .eq(User::getPhone, user.getPhone()));
        if (userList.isEmpty()) {
            throw new GlobalException(Status.LOGIN_ERROR);
        } else if (userList.size() != 1) {
            log.error("出现存在多用户情况");
            throw new GlobalException(Status.SYS_ERROR);
        } else {
            User authUser = userList.get(0);
            String pw = user.getPassword();
            Digester digester = DigestUtil.digester("sm3");
            String digesterPw = digester.digestHex(pw);
            boolean auth = authUser.getPassword().equals(digesterPw);
            if (auth) {
                token = JWTUtil.getToken(authUser);
                redisUtil.set("user::"+authUser.getUserId(),
                        token, SYS.USER_TOKEN_TIME, TimeUnit.MINUTES);
                //更新操作时间
                authUser.setLastTime(DateUtil.parse(DateUtil.now()).toJdkDate());
                userMapper.updateById(authUser);
            }else{
                throw new GlobalException(Status.LOGIN_ERROR);
            }
        }
        return token;
    }

    @Override
    public String messageLogin(String phone, String code){
        String token="";
        String verificationCode = (String) redisUtil.get(phone);
        if (StrUtil.isNotBlank(verificationCode) && verificationCode.equals(code)){
            User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getPhone, phone));
            if (user != null){
                token = JWTUtil.getToken(user);
                redisUtil.set("user::"+user.getUserId(),token, SYS.USER_TOKEN_TIME, TimeUnit.MINUTES);
                //更新操作时间
                user.setLastTime(DateUtil.parse(DateUtil.now()).toJdkDate());
                userMapper.updateById(user);
            }
        }

        return token;
    }

    @Override
    public boolean sendMessage(String phone) {
        String code = messageUtil.randomCode();
        if (messageUtil.sendMessage(phone,code)) {
            redisUtil.set(phone,code,5L,TimeUnit.MINUTES);
            return true;
        }else {
            throw new GlobalException(Status.SEND_MSG_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = GlobalException.class)
    public Boolean addUser(User user) {

      /*  if (user.getEmail() != null && !Validator.isEmail(user.getEmail())) {
            throw new GlobalException(Status.ERROR, "邮箱格式不正确");
        }*/
        if (!Validator.isMobile(user.getPhone())) {
            throw new GlobalException(Status.ERROR, "手机号格式不正确");
        }
        User phoneUser = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getPhone, user.getPhone()));
        if (phoneUser != null) {
            throw new GlobalException(Status.EXIST_USER);
        }
        user.setSex(Sex.DEFAULT);
        user.setUserId(IdUtils.getPrimaryKey());
        //密码加密
        String pw = user.getPassword();
        Digester digester = DigestUtil.digester("sm3");
        String digesterPw = digester.digestHex(pw);
        user.setPassword(digesterPw);
        userMapper.insert(user);
        //分配普通用户角色
        userMapper.distributeRole4User(user.getUserId(), RoleType.NORMAL_CUSTOMER.getCode());
        return true;
    }

    @Override
    public Boolean deleteUser(String userId){
       return userMapper.delete(Wrappers.<User>lambdaQuery().eq(User::getUserId,userId))>0;
    }

    public Boolean logout(int userId) {
        //redis 判断token是否过期,
        String key="user::" + userId;
        long expire = redisUtil.getExpire(key);
        if (expire>0){
            redisUtil.delete(key);
        }
        return true;
    }


}


